import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_cytoscape as cyto
import dash_html_components as html
from dash.dependencies import Output, Input

from cytoscape_stylesheet import stylesheet
from project_network2 import elements

cyto.load_extra_layouts()
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.SANDSTONE])

app.layout = dbc.Container(
    dbc.Row([
        dbc.Col(
            cyto.Cytoscape(
                id='cytoscape',
                layout={
                    # 'name': 'klay',
                    'name': 'cola',
                    # 'nodeRepulsion': 5000,
                    # 'idealEdgeLength': 100,
                    # 'edgeElasticity': 0.5,
                    # 'gravity': 0.1,
                    # 'gravityCompound': 3,
                    # 'gravityRangeCompound': 1,
                    # 'nodeDimensionsIncludeLabels': True
                },
                style={'width': '100%', 'height': '95vh', 'background-color': '#ffffff'},
                zoom=1,
                maxZoom=2,
                minZoom=0.01,
                responsive=True,
                boxSelectionEnabled=True,
                elements=elements,
                stylesheet=stylesheet
            ),
            width=10),
        dbc.Col([
            dcc.Dropdown(id="layout",
                         options=[dict(label=i, value=i) for i in ['cola', 'klay', 'cose-bilkent']],
                         value='cola'),
            html.Button(id="export", children="导出"),
            dcc.Slider(
                id='zoom_slider',
                min=0,
                max=2,
                step=0.05,
                value=1,
            ),
            html.Pre(id="cyto_status", children=[]),
            html.Pre(id="cyto_cluster", children=[])
        ],
            width=2)
    ]),
    fluid=True
)

link_node = "clientside_callback"
app.clientside_callback(
    """
    function(selectedNodeData) {
        console.log('link_node');
        cy.elements().removeClass('linked');
        cy.elements().removeClass('unlinked');
        if(selectedNodeData && selectedNodeData.length > 0){
            cy.elements().removeClass('linked');
            var linked = cy.collection();
            for(i = 0; i < selectedNodeData.length; i++){
                var tapNode = cy.$id(selectedNodeData[i]['id']);
                linked = linked.union(tapNode);
                linked = linked.union(tapNode.neighborhood());
            }
            linked = linked.union(linked.parent());
            var unlinked = cy.elements().not(linked);
            console.log('total:'+cy.elements().length);
            console.log('linked:'+linked.length);
            console.log('unlinked:'+unlinked.length);
            unlinked.addClass('unlinked');
            linked.addClass('linked');
            cy.fit(linked, 50);
            unlinked.unselectify();
            unlinked.ungrabify();
            unlinked.unpanify();
            var tapNodeData = tapNode.json()
            return JSON.stringify(tapNodeData);
        }else{
            cy.fit(50);
            cy.elements().selectify();
            cy.elements().grabify();
            cy.elements().panify();
            return [];
        }
    }
    """,
    Output('cyto_status', 'children'),
    Input('cytoscape', 'selectedNodeData'),
)


relayout = "clientside_callback"
app.clientside_callback(
    """
    function(value) {
        if(value){
        var l = cy.layout({name: value});
        console.log('relayout');
        l.run();
        return value;}
    }
    """,
    Output("cytoscape", "layout"),
    Input('layout', 'value')
)


@app.callback(
    Output("cytoscape", "generateImage"),
    Input('export', 'n_clicks')
)
def export_cytoscape(n):
    # if n is not None and n > 0:
    return {
        'type': "png",
        'options': {'full': True, 'scale': 3, 'bg': '#FFF'},
        'action': "download"
    }


change_zoom = "clientside_callback"
app.clientside_callback(
    """
    function(value) {
        cy.zoom(value);
        return cy.zoom();
    }
    """,
    Output('zoom_slider', 'value'),
    Input('zoom_slider', 'drag_value'),
)
#        const triggered = dash_clientside.callback_context.triggered.map(t => t.prop_id);


if __name__ == '__main__':
    app.run_server(debug=False)
